<!--
 头部沉侵模式下，左上角回到首页按钮
 @Author: mosowe
 @Date:2023-01-05 11:20:58
-->

<template>
  <view
    :class="['zo-navbar-component', props.isSticky ? 'sticky' : '']"
    :style="{
      padding: `${rightOffsetTop} 24rpx 20rpx 24rpx`,
      background: `rgba(255,255,255,${bgOpacityNum})`
    }">
    <view class="content">
      <view
        class="left-icon"
        v-if="!props.hideAllBtn">
        <slot name="left">
          <!-- 左侧后退及首页按钮 -->
          <view
            :class="['icon', props.iconBorder ? 'icon-border' : '']"
            :style="{
              borderColor: `rgba(153, 153, 153, ${btnOpacityNum})`,
              color: scrollLen < 20 ? props.iconColor : defaulColor
            }">
            <text
              class="zoicon zo-home"
              v-if="showHomeBtn"
              @click="goHome"></text>
            <text
              class="zoicon zo-arrow-left"
              v-else
              @click="goBack"></text>
          </view>
          <!-- 左侧其他按钮 -->
          <view
            :class="['icon', props.iconBorder ? 'icon-border' : '']"
            :style="{
              borderColor: `rgba(153, 153, 153, ${btnOpacityNum})`,
              color: scrollLen < 20 ? props.iconColor : defaulColor
            }"
            v-if="props.leftIcon"
            @click="leftIconClick">
            <text :class="['zoicon', props.leftIcon]"></text>
          </view>
        </slot>
      </view>
      <!-- 标题 -->
      <slot>
        <view
          class="title"
          :style="{
            opacity: props.defaultHideTitle ? bgOpacityNum : 1,
            color: scrollLen < 20 ? props.titleColor : defaulColor,
            paddingRight: hasSlotRight || props.rightIcon ? '10px' : rightWidth + 'px',
            paddingLeft: props.hideAllBtn
              ? '10px'
              : hasSlotRight || props.rightIcon
              ? `${rightWidth + 42}px`
              : rightWidth + 'px'
          }">
          {{ props.title }}
        </view>
      </slot>

      <!-- 右侧区域 -->
      <view
        class="right-wrap"
        :style="`padding-right: ${
          props.hideAllBtn ? 0 : hasSlotRight || props.rightIcon ? rightWidth : 0
        }px`">
        <slot name="right">
          <view
            :class="['icon', props.iconBorder ? 'icon-border' : '']"
            v-if="props.rightIcon && !props.hideAllBtn"
            :style="{
              borderColor: `rgba(153, 153, 153, ${btnOpacityNum})`,
              color: scrollLen < 20 ? props.iconColor : defaulColor
            }"
            @click="rightIconClick">
            <text :class="['zoicon', props.rightIcon]"></text>
          </view>
        </slot>
      </view>
    </view>
  </view>
</template>

<script lang="ts" setup>
/*
 * 插槽
 * default 默认插槽，标题位
 * left 左侧位
 * right 右侧位
 *
 * 如果需要页面滚动时顶部底色白色渐变，需要在引用的页面显示声明onPageScroll才能触发效果
 * 左侧除回到首页和后退按钮外，额外可以定一个其他按钮，按钮的名称参考zoicon：https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=3848149
 */

import { onPageScroll } from '@dcloudio/uni-app';
import { ref, getCurrentInstance } from 'vue';
const instance = getCurrentInstance();
const defaulColor = ref('rgba(51,51,51,1)'); // 默认颜色

// props定义
interface PropsType {
  title?: string; // 页面标题
  titleColor?: string; // 标题颜色
  leftIcon?: string; // 左侧其他图标
  rightIcon?: string; // 右侧图标
  iconBorder?: boolean; // 图标边框及背景色是否显示
  iconColor?: string; // 图标颜色
  defaultHideTitle?: boolean; // 默认是否隐藏标题
  home?: boolean; // 强制返回首页按钮
  hideAllBtn?: boolean; // 不显示所有按钮
  isSticky?: boolean; // 是否吸顶
  bgLock?: boolean; // 背景色是否锁定，即无背景色
}
const props = withDefaults(defineProps<PropsType>(), {
  title: '',
  rightIcon: '',
  leftIcon: '',
  iconBorder: false,
  iconColor: '#333333',
  titleColor: '#333333',
  defaultHideTitle: false,
  hideAllBtn: false,
  isSticky: false,
  bgLock: false
});

// emits
interface EmitsType {
  (e: 'leftClick'): void;
  (e: 'rightClick'): void;
}
const emits = defineEmits<EmitsType>();

const showHomeBtn = props.home || getCurrentPages().length === 1;

const rightOffsetTop = ref<number | string>(0);
const rightWidth = ref(0);

// #ifdef MP-WEIXIN
const offset = uni.getMenuButtonBoundingClientRect();
rightOffsetTop.value = offset.top + 'px';
rightWidth.value = offset.width;
// #endif

// #ifdef APP-PLUS
rightOffsetTop.value = (uni.getSystemInfoSync()?.statusBarHeight || 0) + 10 + 'px';
rightWidth.value = 0;
// #endif
// #ifdef H5
rightOffsetTop.value = '20rpx';
rightWidth.value = 0;
// #endif

const hasSlotRight = instance?.slots?.right;

const scrollLen = ref(0);
const btnOpacityNum = ref(1);
const bgOpacityNum = ref(0);
// 监听页面滚动，需要引用页面现实声明onPageScroll(()=>{})才能触发
onPageScroll((e) => {
  if (props.bgLock) {
    return;
  }
  scrollLen.value = e.scrollTop;
  btnOpacityNum.value = 50 - e.scrollTop < 0 ? 0 : (50 - e.scrollTop) / 50;
  bgOpacityNum.value = e.scrollTop / 100 > 1 ? 1 : e.scrollTop / 100;
});
// 后退按钮
const goBack = () => {
  uni.navigateBack();
};
// 回到主页
const goHome = () => {
  uni.reLaunch({
    url: '/pages/index/index'
  });
};
// 左侧其他按钮点击事件
const leftIconClick = () => {
  emits('leftClick');
};
// 右侧其他按钮点击事件
const rightIconClick = () => {
  emits('rightClick');
};
</script>

<style scoped lang="scss">
.zo-navbar-component {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  z-index: 9999;
  box-sizing: border-box;
  &.sticky {
    position: sticky !important;
  }
  .content {
    display: flex;
    position: relative;
    height: 64rpx;
  }
  .left-icon {
    position: absolute;
    left: -24rpx;
    top: 0;
    z-index: 8;
  }
  .icon {
    width: 64rpx;
    height: 64rpx;
    line-height: 64rpx;
    text-align: center;
    display: inline-block;
    color: #333;
    &:nth-child(1) {
      margin-left: 20rpx;
    }
    &.icon-border {
      margin-left: 20rpx;
      border-radius: 50%;
      border: 1px solid #999;
      background-color: rgba(255, 255, 255, 0.6);
    }
    .zoicon {
      font-size: 40rpx;
    }
  }
  .title {
    flex: 1;
    text-align: center;
    line-height: 64rpx;
    font-size: 34rpx;
    font-weight: bold;
    color: #333333;
    opacity: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}
</style>
